package org.gpp.proj1.camera.action;

import com.jme.math.Vector3f;
import com.jme.scene.CameraNode;

/**
 * 
 * @author Paolo Victor, paolovictor@gmail.com
 */
public class MoveToPointAction implements CameraAction {
	
	/**
	 * The time passed since the action start
	 */
	private float elapsedTime;
	
	/**
	 * The action's duration
	 */
	private float actionDuration;

	/**
	 * Defines if the action is finished
	 */
	private boolean finished;

	/**
	 * The quaternion that represents the point
	 * that the camera will be on the action's end
	 */
	private Vector3f targetTranslation;

	/**
	 * The quaternion that represents the camera's
	 * initial translation
	 */
	private Vector3f initialTranslation;

	/**
	 * The controlled camera
	 */
	private CameraNode camera;
	
	/**
	 * Default constructor
	 * @param camera
	 * @param point
	 * @param actionDuration
	 */
	public MoveToPointAction( CameraNode camera, Vector3f point, float actionDuration ) {
		assert camera != null : "Cannot create action with a null camera";
		assert point != null : "Cannot create action with a null point";
		assert actionDuration >= 0.0f : "Cannot create action with a negative duration";
		
		this.finished = false;
		this.actionDuration = actionDuration;
		
		this.elapsedTime = 0.0f;
		this.camera = camera;
		
		this.targetTranslation = point;
	}

	public void updateAction(float timePerFrame, CameraNode cameraNode ) {		
		// If finished, do nothing
		if( finished ) {
			return;
		}
		
		// If it's the first iteration, get the initial direction
		if( elapsedTime == 0.0f ) {
			this.initialTranslation = new Vector3f( camera.getLocalTranslation() );
		}
		
		// Updating ticks and rotating camera node towards point
		elapsedTime += timePerFrame;
		
		if( elapsedTime >= actionDuration ) {
			finished = true;
			cameraNode.setLocalTranslation( targetTranslation );
			cameraNode.updateGeometricState( 0.0f, true );
			return;			
		}
		
		float newX = initialTranslation.x + (targetTranslation.x - initialTranslation.x) / actionDuration * elapsedTime;
		float newY = initialTranslation.y + (targetTranslation.y - initialTranslation.y) / actionDuration * elapsedTime;
		float newZ = initialTranslation.z + (targetTranslation.z - initialTranslation.z) / actionDuration * elapsedTime;
		
		cameraNode.setLocalTranslation( new Vector3f( newX, newY, newZ ) );
		cameraNode.updateGeometricState( 0.0f, true );
	}

	public boolean isFinished() {
		return finished;
	}

}
